﻿using System;
using System.Collections.Generic;
using System.Transactions;
using T.FAS.Runtime.Metadata.Entity.DataModel;
using T.ServiceComponent.DAC.Service;
using T.FAS.Runtime.Base.Dao;
using T.FAS.Runtime.Base.Entity;
using ICSharpCode.SharpZipLib.Core;

namespace T.FAS.Runtime.DataModel.Dao
{
    /// <summary>
    /// CNO ELB数据访问类
    /// </summary>
    public class AssociationELBDao : DaoService<Association>
    {
        public override string TableName => "FAS_Association";
        public override string IDColumnName => "ID";
        public string ForeignColumn => "CompositeNodeObjectID";
        public string MetaDataForeignColumn => "CompositeDataObjectID";
        public override List<string> ExceptColumnName {get;} = DaoUtil.GetExceptionColumn<Association>();

        private readonly AssociateItemELBDao _associateItemELBDao = new AssociateItemELBDao();
        private readonly AssociationRefElementELBDao _associationRefElementELBDao = new AssociationRefElementELBDao();

        public AssociationELBDao() : base()
        {
            DBName = "TFAS";
        }

        public override Dictionary<string, object> GetDataMapping(Association data)
        {
            var mapping = base.GetDataMapping(data);
            mapping.Remove(nameof(Association.AssociateType));

            mapping.Add(nameof(Association.AssociateType), (int)data.AssociateType);

            return mapping;
        }

        /// <summary>
        /// 获取元数据内容
        /// </summary>
        /// <param name="cnoId"></param>
        /// <returns></returns>
        public List<Association> GetAssociations(string cnoId)
        {
            var result = new List<Association>();
            if (string.IsNullOrEmpty(cnoId))
            {
                return result;
            }
            //List<object> objects = base.GetObjectsByFilter($"{ForeignColumn}='{CNOId}'");
            var dt = base.GetByFilter($"{ForeignColumn}='{cnoId}'");
            var objects = DaoUtil.ConvertToEntity<Association>(dt, this.ExceptColumnName);
            if (objects != null)
            {
                return objects;
                //objects.ForEach(obj => {
                //    var asso = obj as Association;
                //    //asso.Items = AssociateItemELBDao.GetAssociateItems(asso.ID);
                //    //asso.RefElements = AssociationRefElementELBDao.GetAssociationRefElements(asso.ID);
                //    result.Add(asso);
                //});
            }
            return result;
        }

        /// <summary>
        /// 获取元数据内容
        /// </summary>
        /// <param name="cdoId"></param>
        /// <returns></returns>
        public List<Association> GetAssociationsByMetaDataForeignKey(string cdoId)
        {
            var result = new List<Association>();
            if (string.IsNullOrEmpty(cdoId))
            {
                return result;
            }
            var dt = base.GetByFilter($"{MetaDataForeignColumn}='{cdoId}'");
            var objects = DaoUtil.ConvertToEntity<Association>(dt, this.ExceptColumnName);
            if (objects != null)
            {
                return objects;
            }
            return result;
        }

        /// <summary>
        /// 添加Association|Item|RefElement
        /// </summary>
        /// <param name="associations"></param>
        public void CreateAssociation(List<Association> associations)
        {
            try
            {
                List<AssociateItem> Items = new List<AssociateItem>();
                List<AssociationRefElement> Eles = new List<AssociationRefElement>();
                base.Add(new List<object> { associations });
                foreach (var asso in associations)
                {
                    if (asso.Items != null && asso.Items.Count > 0)
                        Items.AddRange(asso.Items);
                    if (asso.RefElements != null && asso.RefElements.Count > 0)
                        Eles.AddRange(asso.RefElements);
                }
                using (var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions() { IsolationLevel = IsolationLevel.ReadCommitted }))
                {
                    base.Add(associations);
                    _associateItemELBDao.Add(Items);
                    _associationRefElementELBDao.Add(Eles);
                    scope.Complete();
                }
            }
            catch (Exception e)
            {

                throw new FasException(DataModelErrorCode.CDO.CreateAssoError, e.Message, e);
            }
        }

        /// <summary>
        /// 删除Association|Item|RefElement
        /// </summary>
        /// <param name="Associations"></param>
        public void DeleteAssociation(string cnoId)
        {
            try
            {
                using (var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions(){IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted}))
                {
                    var assos = GetAssociations(cnoId);
                    foreach (var asso in assos)
                    {
                        _associateItemELBDao.DeleteAssociateItem(asso.ID);
                        _associationRefElementELBDao.DeleteAssociationRefElement(asso.ID);
                    }
                    base.DB.ExecSqlStatement(string.Format(DaoUtil.DeleteSQLWithNoParam, this.TableName, this.ForeignColumn, cnoId));
                    scope.Complete();
                } 
            }
            catch (Exception e)
            {

                throw new FasException(DataModelErrorCode.CDO.DeleteAssoError, e.Message, e);
            }
        }

        /// <summary>
        /// 删除Association
        /// </summary>
        /// <param name="metaDataID"></param>
        public void DeleteByMetaDataForeignKey(string metaDataID)
        {
            try
            {
                base.DB.ExecSqlStatement(string.Format(DaoUtil.DeleteSQLWithNoParam, this.TableName, this.MetaDataForeignColumn, metaDataID));
            }
            catch (Exception e)
            {

                throw new FasException(DataModelErrorCode.CDO.DeleteAssoError, e.Message, e);
            }
        }
    }
}
